﻿#include "pinyinhelper.h"
#include "frminput2019.h"

PinYinHelper::PinYinHelper(QObject *parent) : QObject(parent)
{
    input = 0;
}

int PinYinHelper::getScreenIndex()
{
    //需要对多个屏幕进行处理
    int screenIndex = 0;
#if (QT_VERSION >= QT_VERSION_CHECK(5,0,0))
    int screenCount = qApp->screens().count();
#else
    int screenCount = qApp->desktop()->screenCount();
#endif

    if (screenCount > 1) {
        //找到当前鼠标所在屏幕
        QPoint pos = QCursor::pos();
        for (int i = 0; i < screenCount; ++i) {
#if (QT_VERSION >= QT_VERSION_CHECK(5,0,0))
            if (qApp->screens().at(i)->geometry().contains(pos)) {
#else
            if (qApp->desktop()->screenGeometry(i).contains(pos)) {
#endif
                screenIndex = i;
                break;
            }
        }
    }
    return screenIndex;
}

QRect PinYinHelper::getScreenRect(bool available)
{
    QRect rect;
    int screenIndex = getScreenIndex();
    if (available) {
#if (QT_VERSION >= QT_VERSION_CHECK(5,0,0))
        rect = qApp->screens().at(screenIndex)->availableGeometry();
#else
        rect = qApp->desktop()->availableGeometry(screenIndex);
#endif
    } else {
#if (QT_VERSION >= QT_VERSION_CHECK(5,0,0))
        rect = qApp->screens().at(screenIndex)->geometry();
#else
        rect = qApp->desktop()->screenGeometry(screenIndex);
#endif
    }
    return rect;
}

void PinYinHelper::setInput(frmInput2019 *input)
{
    this->input = input;
}

//labCh-硬键盘使用的标签 labCn-横向汉字标签 labMore-更多汉字标签
void PinYinHelper::setLabs(QList<QLabel *> labCh, QList<QLabel *> labCn, QList<QLabel *> labMore)
{
    this->labCh = labCh;
    this->labCn = labCn;
    this->labMore = labMore;
    pinyinCount = labCh.count();
}

int PinYinHelper::getCount()
{
    return pinyinAll.count();
}

//输入法的位置,可以自行调整或者增加设置
void PinYinHelper::movePosition()
{
    //还没有控件则不处理
    if (input->currentWidget == 0) {
        return;
    }

    //浏览器等特殊控件不需要移动位置,移动了反而有坏处
    QStringList classNames;
    classNames << "QQuickWidget" << "QWebView" << "QtWebEngineCore::RenderWidgetHostViewQtDelegateWidget";
    foreach (QString className, classNames) {
        if (input->currentWidget->inherits(className.toLatin1().constData())) {
            return;
        }
    }

    //根据用户选择的输入法位置设置-居中显示-底部填充-显示在输入框正下方
    QRect screenRect = getScreenRect();
    int deskWidth = screenRect.width();
    int deskHeight = screenRect.height();
    int width = input->width();
    int height = input->height();

    if (input->position == "center") {
        QPoint pos = QPoint(deskWidth / 2 - width / 2, deskHeight / 2 - height / 2);
        input->setGeometry(pos.x() + screenRect.x(), pos.y(), width, height);
    } else if (input->position == "bottom") {
        input->setGeometry(0 + screenRect.x(), deskHeight - height, deskWidth, height);
    } else if (input->position == "control") {
        QRect rect = input->currentWidget->rect();
        QPoint pos = QPoint(rect.x(), rect.bottom() + 2);
        pos = input->currentWidget->mapToGlobal(pos);

        //如果输入控件的X坐标+输入法的宽度大于桌面宽度说明右侧部分被遮住,需要X坐标往左平移
        //这里多了个 screenRect.x() 用来处理多个屏幕
        int x = pos.x();
        if ((x - screenRect.x()) + width > deskWidth) {
            x = deskWidth - width + screenRect.x();
        }

        //如果输入控件的Y坐标+输入法的高度大于桌面高度说明下侧部分被遮住,需要显示在控件上方
        int y = pos.y();
        if (y + height > deskHeight) {
            y = y - height - rect.height() - 2;
        }

        //如果XY为负数说明被遮住了部分则居中显示否则按照自动计算的XY值显示
        if (x < 0 || y < 0) {
            QPoint pos = QPoint(deskWidth / 2 - width / 2, deskHeight / 2 - height / 2);
            input->setGeometry(pos.x(), pos.y(), width, height);
        } else {
            input->setGeometry(x, y, width, height);
        }
    }

    //立即刷新界面防止残影,部分嵌入式linux硬件性能差需要刷新
    input->update();
}

bool PinYinHelper::appendChinese(const QString &pinyin, bool insert)
{
    //判断是否超过设定的最大值
    if (pinyinAll.count() >= input->maxCountCn) {
        return false;
    }

    if (insert) {
        pinyinAll.insert(0, pinyin);
    } else {
        pinyinAll.append(pinyin);
    }

    return true;
}

void PinYinHelper::selectChinese(const QString &pinyin)
{
    //清空汉字
    pinyinAll.clear();
    pinyinIndex = 0;

    //对当前的拼音查询汉字,如果超过最大数量的汉字则取前面
    //限制最大的允许输入的拼音字母数量,不限制可能出问题,谷歌拼音输入法的BUG
    int len = pinyin.length();
    if (len > 12) {
        qDebug() << "input too long";
        return;
    }

    //插入用户造词汉字,优先级最高,插入在最前面
    int indexUser = input->userKey.indexOf(pinyin);
    if (indexUser >= 0) {
        QString chineses = input->userValue.at(indexUser);
        QStringList list = chineses.split("|");
        for (int i = list.count() - 1; i >= 0; i--) {
            QString chinese = list.at(i);
            if (chinese.isEmpty() || pinyinAll.contains(chinese)) {
                continue;
            }
            if (!appendChinese(chinese, true)) {
                break;
            }
        }
    }

    //插入用户选定的词,优先级中间,紧随用户造词其后
    int indexSelect = input->selectKey.indexOf(pinyin);
    if (indexSelect >= 0) {
        QString chineses = input->selectValue.at(indexSelect);
        QStringList list = chineses.split("|");
        for (int i = 0; i < list.count(); i++) {
            QString chinese = list.at(i);
            if (chinese.isEmpty() || pinyinAll.contains(chinese)) {
                continue;
            }
            if (!appendChinese(chinese, false)) {
                break;
            }
        }
    }

    //插入查询到的汉字,已经在汉字队列中的过滤
    int count = input->pinyinGoogle.select(pinyin);
    for (int i = 0; i < count; i++) {
        QString chinese = input->pinyinGoogle.getChinese(i);
        if (chinese.isEmpty() || pinyinAll.contains(chinese)) {
            continue;
        }
        if (!appendChinese(chinese, false)) {
            break;
        }
    }

    //显示汉字
    this->pinyin = pinyin;
    showChinese();
}

void PinYinHelper::showChinese()
{
    //隐藏汉字标签
    hideChinese();
    int pyCount = pinyinAll.count();

    //设置实体键盘同步模式下的汉字
    if (input->useHardKeyBoard) {
        //自动计算汉字长度隐藏多余标签 注释掉以后永远按照 chineseCount 个标签的数量显示
        checkChinese(pinyin);
        int count = 0;
        for (int i = pinyinIndex; i < pyCount; i++) {
            QString txt = QString("%1. %2").arg(count + 1).arg(pinyinAll.at(pinyinIndex));
            labCh.at(count)->setText(txt);
            count++;
            pinyinIndex++;
            if (count == pinyinCount) {
                break;
            }
        }
    } else {
        //设置当前拼音对应的汉字 横向汉字框和候选汉字框都设置
        for (int i = 0; i < pyCount; i++) {
            QString text = pinyinAll.at(i);
            labCn.at(i)->setText(text);
            labMore.at(i)->setText(text);
            if (input->hideLabelNoText) {
                labCn.at(i)->setVisible(true);
                labMore.at(i)->setVisible(true);
            }
        }
    }
}

void PinYinHelper::hideChinese()
{
    if (input == 0) {
        return;
    }

    //清空汉字标签
    if (input->useHardKeyBoard) {
        for (int i = 0; i < input->maxCountCh; i++) {
            labCh.at(i)->clear();
            labCh.at(i)->setVisible(false);
        }
    } else {
        for (int i = 0; i < input->maxCountCn; i++) {
            labCn.at(i)->clear();
            labMore.at(i)->clear();
            if (input->hideLabelNoText) {
                labCn.at(i)->setVisible(false);
                labMore.at(i)->setVisible(false);
            }
        }
    }
}

void PinYinHelper::clearChinese()
{
    pinyinAll.clear();
    pinyinIndex = 0;
    hideChinese();
}

void PinYinHelper::showPrevious()
{
    int pyCount = pinyinAll.count();
    if (pinyinIndex >= (pinyinCount * 2)) {
        //每次最多显示汉字数,所以每次向前的时候索引要减 数量 * 2
        if (pinyinIndex % pinyinCount == 0) {
            pinyinIndex -= (pinyinCount * 2);
        } else {
            pinyinIndex = pyCount - (pyCount % pinyinCount) - pinyinCount;
        }
    } else {
        pinyinIndex = 0;
    }

    showChinese();
}

void PinYinHelper::showNext()
{
    if (pinyinIndex < pinyinAll.count() - 1) {
        showChinese();
    }
}

void PinYinHelper::checkChinese(const QString &pinyin)
{
    if (!input->useHardKeyBoard) {
        return;
    }

    //根据当前拼音长度自动隐藏标签
    int len = pinyin.length();
    if (len > 8) {
        setChVisible(input->maxCountCh - 4);
    } else if (len > 6) {
        setChVisible(input->maxCountCh - 3);
    } else if (len > 4) {
        setChVisible(input->maxCountCh - 2);
    } else if (len > 2) {
        setChVisible(input->maxCountCh - 1);
    } else {
        setChVisible(input->maxCountCh);
    }
}

void PinYinHelper::setChVisible(int index)
{
    pinyinCount = index;
    for (int i = 0; i < input->maxCountCh; i++) {
        labCh.at(i)->setVisible(i < index);
    }
}
